<?php

defined('SYSPATH') or die('No direct script access.');

class Ads_Cianrds extends Ads implements Ads_Interface {

	public function __construct($config) {
		parent::__construct($config);
		$this->_typeid = Arr::get($this->_config, 'typeid', null);
		if (empty($this->_typeid)) {
			throw new Ads_Exception('No Ads typeid defined in configuration');
		}
		$this->_database = Arr::get($this->_config, 'database', null);
		if (empty($this->_database)) {
			throw new Ads_Exception('No Ads database defined in configuration');
		}
		$this->_livetime = Arr::get($this->_config, 'livetime', null);
		if (empty($this->_livetime)) {
			throw new Ads_Exception('No Ads livetime defined in configuration');
		}
		if (class_exists('phpQuery') === FALSE) {
			throw new Ads_Exception('"phpQuery" requires');
		}
		try {
			$this->redis = RedisDB::instance();
		}
		catch (Database_Exception $e) {
			Kohana::$log->add(Log::ERROR, Kohana_Exception::text($e))->write();
		}
		return;
	}

	public function parse($html = '') {
		if (empty($html)) {
			$html = &$this->_data;
		}
		$document = phpQuery::newDocument($html);
		$rows = pq("table.cat tr[id^='tr_']");
		foreach ($rows as $row) {
			pq($row)->find("br")->replaceWith(" ");
			pq($row)->find("div.complaint")->replaceWith("");
			pq($row)->find("span.np")->replaceWith("");
			$id = str_replace('tr_', '', pq($row)->attr('id'));
			$data[$id]['adsid'] = $id;
			$data[$id]['distance'] = pq($row)->find("td[id$='_metro']")->clone()->children()->remove()->end()->text();
			for ($i = 0; $i < pq($row)->find("td[id$='_metro'] a")->length; $i++) {
				$_text = pq($row)->find("td[id$='_metro'] a")->eq($i)->text();
				$_href = str_replace('/cat.php?deal_type=1&', '', pq($row)->find("td[id$='_metro'] a")->eq($i)->attr('href'));
				if (preg_match('`^obl_id=(\d+)$`si', $_href)) {
					$data[$id]['city'] = $_text;
				}
				elseif (preg_match('`^obl_id=(\d+)&street\[0\]=(\d+)$`si', $_href)) {
					$data[$id]['street'] = $_text;
					$data[$id]['cityid'] = $m[1];
				}
				elseif (preg_match('`^obl_id=(\d+)&street\[0\]=(\d+)&house=(\d+)&ohn=(\d+)$`si', $_href)) {
					$data[$id]['house'] = $_text;
					$data[$id]['cityid'] = $m[1];
				}
				elseif (preg_match('`^obl_id=(\d+)&metro\[0\]=(\d+)$`si', $_href, $m)) {
					$data[$id]['metro'] = $_text;
					$data[$id]['cityid'] = $m[1];
					$data[$id]['metroid'] = $m[2];
				}
			}
			$data[$id]['room'] = pq($row)->find("td[id$='_room'] a")->text();
			$data[$id]['rooms'] = pq($row)->find("td[id$='_rooms']")->text();
			$data[$id]['price'] = pq($row)->find("td[id$='_price']")->text();
			$data[$id]['floor'] = pq($row)->find("td[id$='_floor']")->text();
			$data[$id]['dopsved'] = pq($row)->find("td[id$='_dopsved']")->text();
			$data[$id]['com'] = pq($row)->find("td[id$='_com']")->text();
			$data[$id]['contacts'] = implode(',', preg_split("/[\s]+/", UTF8::trim(pq($row)->find("td[id$='_contacts'] a")->text())));
			$data[$id]['datetime'] = pq($row)->find("td[id$='_comment'] span[id^='added_']")->text();
			$data[$id]['comment'] = pq($row)->find("td[id$='_comment']")->clone()->children()->remove()->end()->text();
			$data[$id]['url'] = 'http://www.cian.ru' . pq($row)->find("td[id$='_comment'] a[href^='/rent/flat/']")->eq(0)->attr('href');
			$data[$id]['added'] = time();
			$data[$id]['rent'] = 0;
			if (UTF8::strpos($data[$id]['price'], 'сутки') !== FALSE) {
				$data[$id]['rent'] = 1;
			}
			list($data[$id]['floorid'], ) = explode('/', $data[$id]['floor']);
			if (preg_match('`([0-9,]+)р.`si', $data[$id]['price'], $m)) {
				$data[$id]['cost'] = str_replace(',', '', $m[1]);
			}
			else {
				$data[$id]['cost'] = 0;
			}
			if (UTF8::strpos($data[$id]['room'], 'комната') !== FALSE) {
				$data[$id]['roomid'] = 0;
			}
			elseif (preg_match('`(\d)-`si', $data[$id]['room'], $m)) {
				$data[$id]['roomid'] = $m[1];
			}
		}
		foreach ($data as $id => &$arr) {
			foreach ($arr as $field => &$str) {
				if ($field != 'contacts') {
					$str = preg_replace('"\s+"si', ' ', UTF8::trim(str_replace('&nbsp;', ' ', $str)));
				}
			}
		}
		return $data;
	}

	public function write($data) {
		$costs = array(
			1 => array(0, 500),
			2 => array(501, 1000),
			3 => array(1001, 2000),
			4 => array(2001, 5000),
			5 => array(5001, 10000),
			6 => array(1001, 15000),
			7 => array(15001, 20000),
			8 => array(20001, 25000),
			9 => array(25001, 30000),
			10 => array(30001, 35000),
			11 => array(35001, 40000),
			12 => array(40001, 45000),
			13 => array(45001, 50000),
			14 => array(50001, 55000),
			15 => array(55001, 60000),
			16 => array(60001, 65000),
			17 => array(65001, 70000),
			18 => array(70001, 85000),
			19 => array(75001, 80000),
			20 => array(80001, 85000),
			21 => array(85001, 90000),
			22 => array(90001, 95000),
			23 => array(95001, 100000),
			24 => array(100001, 105000),
			25 => array(105001, 110000),
			26 => array(110001, 115000),
			27 => array(115001, 120000),
			28 => array(120001, 125000),
			29 => array(125001, 130000),
			30 => array(130001, 135000),
			31 => array(135001, 140000),
			32 => array(140001, 145000),
			33 => array(145001, 150000),
		);
		foreach ($data as $adsid => &$ads) {
			if ($this->redis->exists('ads:' . $adsid) === FALSE) {
				$this->redis->set('ads:' . $adsid, serialize($ads));
				$this->redis->sAdd('ads_group_city:' . $ads['cityid'], 'ads:' . $adsid);
				$this->redis->sAdd('ads_group_metro:' . $ads['metroid'], 'ads:' . $adsid);
				$this->redis->sAdd('ads_group_room:' . $ads['roomid'], 'ads:' . $adsid);
				$this->redis->sAdd('ads_group_floor:' . $ads['floorid'], 'ads:' . $adsid);
				$this->redis->sAdd('ads_group_rent:' . $ads['rent'], 'ads:' . $adsid);

				$costset = FALSE;
				foreach ($costs as $costid => &$costrange) {
					if ($costrange[0] <= $ads['cost'] AND $costrange[1] >= $ads['cost']) {
						$this->redis->sAdd('ads_group_cost:' . $costid, 'ads:' . $adsid);
						$costset = TRUE;
						break;
					}
				}
				if (!$costset) {
					$this->redis->sRem('ads_group_cost:34', 'ads:' . $adsid);
				}

				$this->redis->zAdd('ads_range', $ads['added'], 'ads:' . $adsid);
			}
		}
		$tmax = time() - 7 * 86400;
		$tmin = time() - 8 * 86400;
		$del_ads_range = $this->redis->zRevRangeByScore('ads_range', $tmax, $tmin, array('withscores' => TRUE));
		$this->redis->zDeleteRangeByScore('ads_range', $tmin, $tmax);
		$ads_range = $this->redis->mGet(array_keys($del_ads_range));
		$this->redis->delete(array_keys($del_ads_range));

		foreach ($ads_range as &$ads) {
			$this->redis->sRem('ads_group_city:' . $ads['cityid'], 'ads:' . $ads['adsid']);
			$this->redis->sRem('ads_group_metro:' . $ads['metroid'], 'ads:' . $ads['adsid']);
			$this->redis->sRem('ads_group_room:' . $ads['roomid'], 'ads:' . $ads['adsid']);
			$this->redis->sRem('ads_group_floor:' . $ads['floorid'], 'ads:' . $ads['adsid']);
			$this->redis->sRem('ads_group_rent:' . $ads['rent'], 'ads:' . $ads['adsid']);
			$costset = FALSE;
			foreach ($costs as $costid => &$costrange) {
				if ($costrange[0] <= $ads['cost'] AND $costrange[1] >= $ads['cost']) {
					$this->redis->sRem('ads_group_cost:' . $costid, 'ads:' . $ads['adsid']);
					$fostset = TRUE;
					break;
				}
			}
			if (!$costset) {
				$this->redis->sRem('ads_group_cost:' . $costid, $ads['adsid']);
			}
		}
	}

	public function readnew($limit = 20) {
		unset($this->_ads);
		$db = Database::instance($this->_database);
		$_adsids = DB::select('adsid')->from('adsts')->order_by('timestamp', 'DESC')->limit($limit)->execute($this->_database)->as_array();

		foreach ($_adsids as &$adsid) {
			$this->_adslist[$adsid['adsid']] = $this->read($adsid['adsid'])->as_array();
		}
		return $this->_adslist;
	}

	public function read($adsid) {
		unset($this->_ads);
		$db = Database::instance($this->_database);
		$_ads = DB::select('field', 'value')->from('ads')->where('typeid', '=', $this->_typeid)->and_where('adsid', '=', $adsid)->execute($this->_database)->as_array();
		foreach ($_ads as &$arr) {
			$this->_ads[$arr['field']] = $arr['value'];
		}
		return $this;
	}

	public function as_array() {
		return $this->_ads;
	}

	public function get($key, $default = NULL) {
		if (Arr::get($this->_ads, $key, $default) == NULL) {
			throw new Ads_Exception('No field in Ads: "' . $key . '"');
		}
		else {
			return Arr::get($this->_ads, $key, $default);
		}
	}

	public function count() {
		//$keys = $this->redis->keys('ads:*');
		return $this->redis->zSize('ads_range');
		//return count($keys); //DB::select(array(DB::expr('COUNT(*)'), 'count'))->from('adsts')->execute($this->_database)->get('count', 0);
	}

	public function search($post) {
		$t = microtime(true);
		foreach ($post as $key => &$data) {
			if (is_array($data)) {
				sort($data);
				$dst[] = 'ads_group_' . $key . ':' . implode('_', $data);
				if (count($data) > 1) {
					$param[] = 'ads_group_' . $key . ':' . implode('_', $data);
					foreach ($data as &$val) {
						$param[] = 'ads_group_' . $key . ':' . $val;
					}
					echo '<pre>';
					print_r($param);
					echo '</pre>';
					call_user_func_array(array($this->redis, 'sUnionStore'), $param);
					unset($param);
				}
			}
			else {
				$dst[] = 'ads_group_' . $key . ':' . $data;
			}
		}

		if (count($dst) > 1) {
			array_unshift($dst, 'ads_search');
			call_user_func_array(array($this->redis, 'sInterStore'), $dst);
		}
		echo '<pre>';
		print_r($dst);
		echo '</pre>';
		$this->redis->zInter('ads_result', array('ads_range', array_shift($dst)));
		echo 'найдено: '.$this->redis->zSize('ads_result').'<br>'.PHP_EOL;
		$adsids = $this->redis->zRevRangeByScore('ads_result', time(), time() - 7 * 86400, array('limit' => array(0, 50)));

		$tt = 0;

		$adsids = $this->redis->mGet($adsids);
		$tt2 = microtime(true) - $t;
		foreach ($adsids as &$ads) {
			$t = microtime(true);
			$this->_ads[] = unserialize($ads);
			$tt += microtime(true) - $t;
		}
		$del = $this->redis->keys('ads_group_*:*_*');
		$del[] = 'ads_search';
		$del[] = 'ads_result';
		$this->redis->delete($del);
		unset($adsids);
		echo 'Redis search:' . $tt2 . '<br>';
		echo 'unserialize:' . $tt . '<br>';
		return $this->_ads;
	}

	/* public function query($url, $cache = FALSE) {

	  $url_parts=parse_url($url);
	  parse_str($url_parts['query'], $get_array);
	  $url=$url_parts['scheme'].'://'.$url_parts['host'].$url_parts['path'];
	  $request = Request::factory($url)
	  ->query($get_array)
	  ->method(Request::GET);
	  $request->client()
	  ->options(array(
	  CURLOPT_SSL_VERIFYPEER => FALSE,
	  CURLOPT_USERAGENT => empty(Request::$user_agent)?Request::$user_agent:'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36',
	  CURLOPT_HTTPHEADER => array(
	  'Accept-Encoding:gzip,deflate,sdch',
	  'Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
	  ),
	  CURLOPT_FOLLOWLOCATION => TRUE,
	  CURLOPT_COOKIEFILE => APPPATH . "config/cookie.file",
	  CURLOPT_COOKIEJAR => APPPATH . "config/cookie.file",
	  ));
	  $response = $request->execute();
	  $data = $response->body();

	  $this->_data = $data;
	  return $this;
	  } */
}
